package com.rs.util;

import cn.hutool.core.util.StrUtil;
import com.rs.cache.LocalCache;
import com.rs.entity.basic.MapDataPointVO;

import java.math.BigDecimal;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zhouwz
 * @date 2020/7/19 19:56
 */
public class CoordinatorNodeUtil {

    /**
     * 获取坐标字典
     *
     * @return 获取坐标字典
     */
    public static Map<String, MapDataPointVO> getCoordinateMap() {
        return LocalCache.coordinateMap;
    }

    /**
     * 获取指定坐标点对象
     *
     * @param code 坐标点
     * @return 获取指定坐标点对象
     */
    public static MapDataPointVO get(String code) {
        return getCoordinateMap().get(code);
    }

    /**
     * 获取指定坐标点对象
     *
     * @param x x轴
     * @param y y轴
     * @return 获取指定坐标点对象
     */
    public static MapDataPointVO get(BigDecimal x, BigDecimal y) {
        return getCoordinateMap().get(StrUtil.format("{},{}", x, y));
    }

    /**
     * 获取指定坐标点对象
     *
     * @param x x轴
     * @param y y轴
     * @return 获取指定坐标点对象
     */
    public static MapDataPointVO put(BigDecimal x, BigDecimal y, MapDataPointVO mapDataPointVO) {
        return getCoordinateMap().put(StrUtil.format("{},{}", x, y), mapDataPointVO);
    }

    /**
     * 新增点位对象信息
     *
     * @param mapDataPoint 点位对象
     */
    public static void put(MapDataPointVO mapDataPoint) {
        put(mapDataPoint.getXCoordinate(), mapDataPoint.getYCoordinate(), mapDataPoint);
    }

    /**
     * 车编号:对应坐标
     */
    public static volatile Map<String, Set<BigDecimal>> processPoints = new ConcurrentHashMap<>();

    /**
     * 往上走,点位y坐标在当前和目标区间内的
     *
     * @param currentY    当前y坐标
     * @param targetX     目标x坐标
     * @param targetY     目标y坐标
     * @param vehicleCode 车辆编号
     */
    public static void upBetween(BigDecimal currentY, BigDecimal targetX, BigDecimal targetY, String vehicleCode) {
        for (String coordinateKey : getCoordinateMap().keySet()) {
            if (coordinateKey.startsWith(targetX.toString())) {
                Double y = Double.parseDouble(coordinateKey.substring(coordinateKey.indexOf(",") + 1));
                // 当前y坐标 < 途径y坐标 < 终点y坐标
                if (y.compareTo(targetY.doubleValue()) < 0 && y.compareTo(currentY.doubleValue()) > 0) {
                    Set<BigDecimal> processNodes = processPoints.get(vehicleCode);
                    BigDecimal throughY = new BigDecimal(String.valueOf(y)).setScale(3, BigDecimal.ROUND_HALF_UP);
                    addThroughNodeCoordinator(vehicleCode, processNodes, throughY);
                }
            }
        }
    }

    /**
     * 往下走,点位y坐标在当前和目标区间内的
     *
     * @param currentY    当前y坐标
     * @param targetX     目标x坐标
     * @param targetY     目标y坐标
     * @param vehicleCode 车辆编号
     */
    public static void downBetween(BigDecimal currentY, BigDecimal targetX, BigDecimal targetY, String vehicleCode) {
        for (String coordinateKey : getCoordinateMap().keySet()) {
            if (coordinateKey.startsWith(targetX.toString())) {
                Double y = Double.parseDouble(coordinateKey.substring(coordinateKey.indexOf(",") + 1));
                // 终点y坐标 < 途径点y坐标 < 当前y坐标
                if (y.compareTo(targetY.doubleValue()) > 0 && y.compareTo(currentY.doubleValue()) < 0) {
                    Set<BigDecimal> processNodes = processPoints.get(vehicleCode);
                    BigDecimal throughY = new BigDecimal(String.valueOf(y)).setScale(3, BigDecimal.ROUND_HALF_UP);
                    addThroughNodeCoordinator(vehicleCode, processNodes, throughY);
                }
            }
        }
    }

    /**
     * 往左走,点位x坐标在当前和目标区间内的
     *
     * @param currentX    当前x坐标
     * @param targetX     目标x坐标
     * @param targetY     目标y坐标
     * @param vehicleCode 车辆编号
     */
    public static void leftBetween(BigDecimal currentX, BigDecimal targetX, BigDecimal targetY, String vehicleCode) {
        for (String coordinateKey : getCoordinateMap().keySet()) {
            if (coordinateKey.endsWith(targetY.toString())) {
                Double x = Double.parseDouble(coordinateKey.substring(0, coordinateKey.indexOf(",")));
                // 终点x坐标 < 途径x坐标 < 当前x坐标
                if (x.compareTo(targetX.doubleValue()) > 0 && x.compareTo(currentX.doubleValue()) < 0) {
                    Set<BigDecimal> processNodes = processPoints.get(vehicleCode);
                    BigDecimal throughX = new BigDecimal(String.valueOf(x)).setScale(3, BigDecimal.ROUND_HALF_UP);
                    addThroughNodeCoordinator(vehicleCode, processNodes, throughX);
                }
            }
        }
    }

    /**
     * 往右走,点位x坐标在当前和目标区间内的
     *
     * @param currentX    当前x坐标
     * @param targetX     目标x坐标
     * @param targetY     目标y坐标
     * @param vehicleCode 车辆编号
     */
    public static void rightBetween(BigDecimal currentX, BigDecimal targetX, BigDecimal targetY, String vehicleCode) {
        for (String coordinateKey : getCoordinateMap().keySet()) {
            if (coordinateKey.endsWith(targetY.toString())) {
                Double x = Double.parseDouble(coordinateKey.substring(0, coordinateKey.indexOf(",")));
                // 当前x坐标 < 途径点x坐标 < 终点x坐标
                if (x.compareTo(targetX.doubleValue()) < 0 && x.compareTo(currentX.doubleValue()) > 0) {
                    Set<BigDecimal> processNodes = processPoints.get(vehicleCode);
                    BigDecimal throughX = new BigDecimal(String.valueOf(x)).setScale(3, BigDecimal.ROUND_HALF_UP);
                    addThroughNodeCoordinator(vehicleCode, processNodes, throughX);
                }
            }
        }
    }

    /**
     * 添加途径的点位坐标
     *
     * @param vehicleCode        车辆编号
     * @param processNodes       经过的点位集合
     * @param throughCoordinator 经过的坐标
     */
    private static void addThroughNodeCoordinator(String vehicleCode, Set<BigDecimal> processNodes, BigDecimal throughCoordinator) {
        if (processNodes != null) {
            processNodes.add(throughCoordinator);
        } else {
            Set<BigDecimal> sortSet = new TreeSet<>();
            sortSet.add(throughCoordinator);
            processPoints.put(vehicleCode, sortSet);
        }
    }
}
